package edu.umb.cs.antmanager.client;

import java.io.File;
import java.io.PrintStream;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.XmlLogger;

import edu.umb.cs.antmanager.domain.PropertyType;
import edu.umb.cs.antmanager.domain.TestType;
import static edu.umb.cs.antmanager.common.Constants.*;

/**
 * The <code>AntRunner</code> implements <tt>Runnable</tt> will run any ant task
 * defined by <code>TestType</code> and save the result as xml file, if the
 * callback object <code>RMIAgentServer</code> is given, it will call the
 * <code>freeServer</code> method defined in <code>RMIAgentServer</code> after
 * the task execution finished.
 * 
 * @author 2009CS682-3UMB_AntManager
 * 
 */
public class AntRunner implements Runnable {
	private TestType test;
	private RMIAgentServer server;
	private PrintStream logPrinter;

	/**
	 * Construct an <tt>AntRunner</tt> with call back object.
	 * 
	 * @param test
	 *            <tt>TestType</tt> which contains all the information about a
	 *            test
	 * @param server
	 *            The agent's server object, used to let the server know when
	 *            task finished
	 */
	public AntRunner(TestType test, RMIAgentServer server,
			PrintStream logPrinter) {
		this.test = test;
		this.server = server;
		this.logPrinter = logPrinter;
	}

	/**
	 * For test purpose, no call back object , it just run the task
	 * 
	 * @param test
	 *            <tt>TestType</tt> which contains all the information about a
	 *            test
	 */
	public AntRunner(TestType test) {
		this(test, null, System.out);
	}

	@Override
	/*
	 * Start the ant task.
	 */
	public void run() {
		// The ant file contains the test target
		File buildFile = new File(ANT_MANAGER_HOME + test.getFile());
		Project p = new Project();
		// set the ant file
		p.setUserProperty("ant.file", buildFile.getAbsolutePath());

		// add by zexu for XML logging
		// set the xml log file
		p.setUserProperty("XmlLogger.file", ANT_MANAGER_HOME + test.getName()
				+ ".xml");
		// no style sheet for the xml file
		p.setUserProperty("ant.XmlLogger.stylesheet.uri", "");
		XmlLogger xmlLogger = new XmlLogger();
		// TODO maybe we should have some mechanism to set the log level at run
		// time
		xmlLogger.setMessageOutputLevel(Project.MSG_INFO);
		p.addBuildListener(xmlLogger);
		
		//this logger is flushed automatically, used for GUI's live log function
		DefaultLogger liveLogger = new DefaultLogger();
		liveLogger.setErrorPrintStream(logPrinter);
		liveLogger.setOutputPrintStream(logPrinter);
		liveLogger.setMessageOutputLevel(Project.MSG_INFO);
		p.addBuildListener(liveLogger);

		try {
			p.fireBuildStarted();
			p.init();
			ProjectHelper helper = ProjectHelper.getProjectHelper();
			p.addReference("ant.projectHelper", helper);
			helper.parse(p, buildFile);
			// set properties
			for (PropertyType prop : test.getPropertyArray()) {
				p.setProperty(prop.getName(), prop.getValue());
			}
			p.executeTarget(test.getTarget());
			p.fireBuildFinished(null);
		} catch (BuildException e) {
			p.fireBuildFinished(e);
		} finally {
			if (server != null)
				// notify the server
				server.freeServer();
		}
	}
}
